package generic.queue;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class EventQueue<T>{

	private int QUEUE_SIZE=5;
	
	private BlockingQueue<IEvent<T>> consumerQueue=new ArrayBlockingQueue<IEvent<T>>(QUEUE_SIZE,false);
	private BlockingQueue<IEvent<T>> producerQueue=new ArrayBlockingQueue<IEvent<T>>(QUEUE_SIZE,false);
	
	private EventConsumer<T> consumer;
	private Map<String, IHandler<T>> handlers;
	
	private IEventFactory<T> eventFactory;
	
	public EventQueue(IEventFactory<T> eventFactory) {
		handlers = new HashMap<String, IHandler<T>>();
		
		for(int i=0;i<QUEUE_SIZE;i++){
			producerQueue.add(eventFactory.create());
		}
		
		consumer=new EventConsumer<T>(this);
		consumer.start();
	}
	
	public synchronized IEvent<T> get() throws InterruptedException{
		return producerQueue.take();
	}
	
	public synchronized void publish(IEvent<T> event){
		while(consumerQueue.size()>=QUEUE_SIZE)
			try {
				System.out.println("Queue full, waiting...");
				this.wait(10);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		consumerQueue.add(event);
	}
	
	public void shutdown(){
		consumer.shutdown();
	}
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public void registerHandler(String eventName, IHandler<T> handler) {
		handlers.put(eventName, handler);
	}

	public IEventFactory<T> getEventFactory() {
		return eventFactory;
	}

	public void setEventFactory(IEventFactory<T> eventFactory) {
		this.eventFactory = eventFactory;
	}

	public BlockingQueue<IEvent<T>> getConsumerQueue() {
		return consumerQueue;
	}

	public BlockingQueue<IEvent<T>> getProducerQueue() {
		return producerQueue;
	}

	public Map<String, IHandler<T>> getHandlers() {
		return handlers;
	}
	
}
